In this project I analyze traffic data from Bloomington in the USA. I focused on Data visualisation, feature engeneering and trying to give advice for the city in order to improve the traffic situation.
I goot the traffic data from data.gov
library(rio)
Paket 㤼㸱rio㤼㸲 wurde unter R Version 4.0.2 erstelltThe following rio suggested packages are not installed: 㤼㸱csvy㤼㸲, 㤼㸱feather㤼㸲, 㤼㸱fst㤼㸲, 㤼㸱hexView㤼㸲, 㤼㸱readODS㤼㸲, 㤼㸱rmatio㤼㸲
Use 'install_formats()' to install them
library(tidyverse)
Paket 㤼㸱tidyverse㤼㸲 wurde unter R Version 4.0.2 erstelltRegistered S3 methods overwritten by 'dbplyr':
method from
print.tbl_lazy
print.tbl_sql
-- Attaching packages --------------------------------------- tidyverse 1.3.0 --
v tibble 3.0.3 v dplyr 1.0.2
v tidyr 1.1.2 v stringr 1.4.0
v readr 1.3.1 v forcats 0.5.0
v purrr 0.3.4
Paket 㤼㸱tibble㤼㸲 wurde unter R Version 4.0.2 erstelltPaket 㤼㸱tidyr㤼㸲 wurde unter R Version 4.0.2 erstelltPaket 㤼㸱readr㤼㸲 wurde unter R Version 4.0.2 erstelltPaket 㤼㸱purrr㤼㸲 wurde unter R Version 4.0.2 erstelltPaket 㤼㸱dplyr㤼㸲 wurde unter R Version 4.0.2 erstelltPaket 㤼㸱stringr㤼㸲 wurde unter R Version 4.0.2 erstelltPaket 㤼㸱forcats㤼㸲 wurde unter R Version 4.0.2 erstellt-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag() masks stats::lag()
x purrr::lift() masks caret::lift()
library(caret)
#read data
traffic <- import("Traffic_dataset.csv")
traffic <- as_tibble(traffic)
traffic
options(dplyr.width = Inf)
#change column names
traffic <- traffic %>%
select(Id = `Master Record Number`, Year, Month, Day, Weekend = `Weekend?`, Hour, Collision_Type = `Collision Type`,
Injury_Type = `Injury Type`, Primary_Factor = `Primary Factor`, Location = Reported_Location, Latitude, Longitude)
Data Description:
Id = Id, primary Key Year = year of accident Month = Month of accident day = day of accident weekend = weekend or not Hour = Hour of accident Collision_Type = Type of collision Injury Type = Type of injury primary_Factor = What was the reason that let the accident happen Location = Where did it happen? Latitude Longutude
#Hour, Latitude and Logitude have NA Columns
#Na check
sapply(traffic, function(x) sum(is.na(x)))
Id Year Month Day Weekend Hour Collision_Type Injury_Type
0 0 0 0 0 225 0 0
Primary_Factor Location Latitude Longitude
0 0 30 30
#Feature Engineering
#Variable check
traffic %>%
glimpse()
Rows: 53,943
Columns: 12
$ Id <int> 902363382, 902364268, 902364412, 902364551, 902364615, 902364664, 902364682, 902364683, 9023647...
$ Year <int> 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015,...
$ Month <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
$ Day <int> 5, 6, 6, 7, 7, 6, 6, 6, 7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 2, 1, 2, 1, 2, 2,...
$ Weekend <chr> "Weekday", "Weekday", "Weekend", "Weekend", "Weekend", "Weekday", "Weekday", "Weekday", "Weeken...
$ Hour <int> 0, 1500, 2300, 900, 1100, 1800, 1200, 1400, 1400, 1600, 1500, 1600, 1700, 1800, 1300, 1500, 180...
$ Collision_Type <chr> "2-Car", "2-Car", "2-Car", "2-Car", "2-Car", "2-Car", "2-Car", "1-Car", "2-Car", "1-Car", "2-Ca...
$ Injury_Type <chr> "No injury/unknown", "No injury/unknown", "Non-incapacitating", "Non-incapacitating", "No injur...
$ Primary_Factor <chr> "OTHER (DRIVER) - EXPLAIN IN NARRATIVE", "FOLLOWING TOO CLOSELY", "DISREGARD SIGNAL/REG SIGN", ...
$ Location <chr> "1ST & FESS", "2ND & COLLEGE", "BASSWOOD & BLOOMFIELD", "GATES & JACOBS", "W 3RD", "BURKS & WAL...
$ Latitude <dbl> 39.15921, 39.16144, 39.14978, 39.16566, 39.16485, 39.12667, 39.15082, 39.19927, 39.16461, 39.16...
$ Longitude <dbl> -86.52587, -86.53485, -86.56889, -86.57596, -86.57962, -86.53137, -86.58490, -86.63702, -86.579...
I will change some variables to better data types
#changing Hour variable into a factor
traffic$Hour <- as.factor(traffic$Hour)
traffic
#changing Id into factor
traffic$Id <- as.factor(traffic$Id)
#changing year,month, day into factor
traffic$Month <- as.factor(traffic$Month)
traffic$Day <- as.factor(traffic$Day)
traffic$Year <- as.factor(traffic$Year)
#Visualization
#In which year are most of the accidents?
ggplot(traffic, aes(Year)) + # all years are equivalent
geom_bar()

#In which month?
ggplot(traffic, aes(Month, fill = Year)) + #overall in month 10 (people have stiill summer wheels and forgot to change them) the most and in month 6 the least
geom_bar() +
facet_grid("Year") #Differences between years

#In which Hour are the most accidents?
ggplot(traffic, aes(Hour)) +
geom_bar()+
coord_cartesian(c(0,24))#18:00 are the most accidents --> people are coming from work to home

#In which day?
ggplot(traffic, aes(Day)) +
geom_bar(aes(fill = Year), color = "black") #Overall the most accidents have been on Saturday (surprisingly)

#Check the Weekend
q <- ifelse(traffic$Day == 1 & traffic$Weekend == "Weekend", T, F)
traffic[-q,] #Surprisingly 1 did not mean "Monday" because their are "Weekdays" and "Weekends" with the factor 1. I would concloud that the Data is a bit Messi. So I will fix it.
#Because the "Weekend" Information is in "Day" (Day 6 & 7 are always Weekends) I can delete that column from the Dataset
traffic <- traffic %>%
select(-Weekend)
#Fixing the NA´s
sapply(traffic, function(x) sum(is.na(x)))
Id Year Month Day Hour Collision_Type Injury_Type Primary_Factor
0 0 0 0 225 0 0 0
Location Latitude Longitude
0 30 30
#NA-Hour
traffic %>%
filter(is.na(Hour))
ggplot(traffic, aes(Collision_Type)) + #Analyzing with Collision Type
geom_bar(aes(fill = Hour), color = "black") #No pattern exist

ggplot(traffic, aes(Location)) + #Analyzing with Location
geom_bar(aes(fill = Hour), color = "black") #Too many

#Filtering all Location that have more than 150 accidents
traffic %>%
group_by(Location) %>%
count(Location) %>%
filter(n >= 150)
#Visualizing
a <- traffic %>%
filter(Location == "3RD ST"| Location == "E 10TH ST"| Location == "E 3RD ST"| Location == "S WALNUT ST"|
Location == "SR37N & VERNAL"| Location == "W 3RD ST") #filtering the most frequent variables
ggplot(a, aes(Location, fill = Hour)) +
geom_bar(color = "black")

#replacing HOur
traffic$Hour <- ifelse(traffic$Location == "3RD ST" & is.na(traffic$Hour), 1500,traffic$Hour)
#Their are just 225 NA in Hour. Compared to 53000 rows, that isnt a large amount. So there is no need to Analyze each type of accident in detail. Therefore we will take the most common accident-Time, which is 18:00.
traffic %>%
group_by(Hour) %>%
count() %>%
filter(n > 3000)
traffic <- traffic %>%
replace_na(list(Hour = 1700))
After we fixed the “Hour” column, we will focuse on the latitude and longitude #Latitude
#Longitude (Bloomingtons Longitude is -88 (searched in google)
#NA´s in longitude
traffic %>%
filter(is.na(Longitude)) %>%
select(Location) %>%
print(n = 100)
#BLOOMFIELD & LIBERTY
traffic %>%
filter(Location == "BLOOMFIELD & LIBERTY") %>%
select(Longitude, Latitude) #The Longitude is 0. That would mean, that this place in Bloomington is in Great Britain. Its obvious, that it cant be right, so i will change the Longitude to the real one found in the internet.
traffic[traffic$Location == "BLOOMFIELD & LIBERTY", "Longitude"] <- -88
#building function
Longi <- function(x) {
traffic %>%
filter(Location == x) %>%
select(Longitude)
}
Longi("BLOOMFIELD & LIBERTY") #works nicely
#DODDS & ROGERS
Longi("DODDS & ROGERS")
traffic[traffic$Location == "DODDS & ROGERS", "Longitude"] <- -86.5
#HARMONY
Longi("HARMONY")
traffic[traffic$Location == "HARMONY", "Longitude"] <- -88
#ALLEN & PATTERSON
Longi("ALLEN & PATTERSON")
traffic[traffic$Location == "ALLEN & PATTERSON", "Longitude"] <- -86.5
#2ND & LINCOLN
Longi("2ND & LINCOLN")
traffic[traffic$Location == "2ND & LINCOLN", "Longitude"] <- -86.5
#FORREST PARK & SR46W
Longi("FORREST PARK & SR46W")
traffic[traffic$Location == "FORREST PARK & SR46W", "Longitude"] <- -86.6
#RHORER & SARE
Longi("RHORER & SARE")
traffic[traffic$Location == "RHORER & SARE", "Longitude"] <- -86.5
#CLUBHOUSE & KINSER
Longi("CLUBHOUSE & KINSER")
traffic[traffic$Location == "CLUBHOUSE & KINSER", "Longitude"] <- -88
#SMITH
Longi("SMITH")
traffic[traffic$Location == "SMITH", "Longitude"] <- -88
#WALNUT & WINSLOW
Longi("WALNUT & WINSLOW")
traffic[traffic$Location == "WALNUT & WINSLOW", "Longitude"] <- -86.5
#BLOOMFIELD & PATTERSON
Longi("BLOOMFIELD & PATTERSON")
traffic[traffic$Location == "BLOOMFIELD & PATTERSON", "Longitude"] <- -88
#2ND & COLLEGE MALL
Longi("2ND & COLLEGE MALL")
traffic[traffic$Location == "2ND & COLLEGE MALL", "Longitude"] <- -86.5
#17TH & LISMORE
Longi("17TH & LISMORE")
traffic[traffic$Location == "17TH & LISMORE", "Longitude"] <- -88
#CORY & THIRD
Longi("CORY & THIRD")
traffic[traffic$Location == "CORY & THIRD", "Longitude"] <- -86.6
#3RD & BALLANTINE
Longi("3RD & BALLANTINE")
traffic[traffic$Location == "3RD & BALLANTINE", "Longitude"] <- -86.5
#3RD & HAWTHORNE
Longi("3RD & HAWTHORNE")
traffic[traffic$Location == "3RD & HAWTHORN", "Longitude"] <- -86.5
#PETE ELLIS
Longi("PETE ELLIS")
traffic[traffic$Location == "PETE ELLIS", "Longitude"] <- -86.5
#3RD & HAWTHORNE
Longi("3RD & HAWTHORNE")
traffic[traffic$Location == "3RD & HAWTHORNE", "Longitude"] <- -86.5
#VERMILYA & WALNUT
Longi("3RD & LIBERTY")
traffic[traffic$Location == "3RD & LIBERTY", "Longitude"] <- -86.6
Longi("3RD & LIBERTY")
traffic[traffic$Location == "3RD & LIBERTY", "Longitude"] <- -86.6
Longi("ALLEN & TIMOTHY")
traffic[traffic$Location == "ALLEN & TIMOTHY", "Longitude"] <- -86.6
#All others have Longitude 86.5
Longi("FAIRFAX & MCCORMICK")
Longi("CANADA & SARE")
Longi("LEONARD SPRINGS & SR45W")
Longi("VERMILYA & WALNUT")
Longi("BLUE SKY & FORREST PARK")
Longi("SOUTHERN & WALNUT")
Longi("3RD & SWAIN")
Longi("DODDS & MADISON")
Longi("OLD STATE ROAD 37 SOUTH & WEST CHUMLEY")
traffic <- traffic %>%
replace_na(list(Longitude = 86.5))
#final NA check
sapply(traffic, function(x) sum(is.na(x)))
Id Year Month Day Hour Collision_Type Injury_Type Primary_Factor
0 0 0 0 0 0 0 0
Location Latitude Longitude
0 0 0
#NA Filling done :D
#0 Wert in Longitude und Location fixen
traffic[traffic$Longitude == 0, "Longitude"] <- -86.5
Now we finished the data cleaning/engeneering part and did some data exploration. Suruly we give advice to fix traffic in general. But we can fokus on the worst cases and see what we can do there. #Which Location has the most dangerous route/ the badest Injury_Type
#Which injury typ exsist?
ggplot(traffic, aes(x = Injury_Type)) +
geom_bar()

#"Incapacitatig" and "fatal" are interesting for us, because we want to make driving car in Bloomington safer. Therefore we need to know the most unsafe locations
trafficBad <- traffic %>%
filter(Injury_Type == "Incapacitating" | Injury_Type == "Fatal")
trafficBad %>%
group_by(Location) %>%
summarise() %>%
print(n = Inf)
`summarise()` ungrouping output (override with `.groups` argument)
#as we can see, we have one Location that is empty "". We have to fix that.
#Filling an empty "" value
trafficBad %>%
filter(Location == "")
trafficBad %>%
group_by(Location) %>%
summarise(count = n()) %>%
summarise(total_number_of_Locations = sum(count))
`summarise()` ungrouping output (override with `.groups` argument)
#since we have 1204 different Location we could try to build a multi label classifier. However, there is just one missig value in one row. Therefor its simply better to analyze the most common Locations with the Latidue and Longitude
trafficBad %>%
group_by(Location) %>%
summarise(count = n()) %>%
arrange(desc(count)) #The most common Location has only a frequency of 8
`summarise()` ungrouping output (override with `.groups` argument)
Because of the low frequency we will do a chi-square test to check, if there are correlations between the Location and the Collisions-Type Hypothesis: #H1: There is a correlation between Location and Collisions-Type #H0: There is no correlation between Location and Collisions-Type
kreuztabelle2 <- table(trafficBad$Location, trafficBad$Collision_Type)
c2 <- chisq.test(kreuztabelle2, simulate.p.value = T)
c2 #p-value < 5%; Therefore a correlation exists.
Pearson's Chi-squared test with simulated p-value (based on 2000 replicates)
data: kreuztabelle2
X-squared = 6639.4, df = NA, p-value = 0.0004998
#We hae to check for "1-Car" because of the empty value.
trafficBad %>%
filter(Collision_Type == "1-Car") %>%
group_by(Location) %>%
summarise(count = n()) %>%
arrange(desc(count)) %>%
print(n = Inf) #Es sind 4 1-Car Collisionstype in "HINDS & SR45W"
`summarise()` ungrouping output (override with `.groups` argument)
#fehlende Location Variable mit "HINDS & SR45W" ersetzen
trafficBad[trafficBad$Id == 1807877, ] <- trafficBad %>%
filter(Id == 1807877) %>%
mutate(Location = "HINDS & SR45W")
#Checking all columns to see if there is any empty value
sapply(trafficBad, function(x) sum(is.na(x))) #No Na
Id Year Month Day Hour Collision_Type Injury_Type Primary_Factor
0 0 0 0 0 0 0 0
Location Latitude Longitude
0 0 0
#Mabe empty one like ""
trafficBad %>%
filter(Month == "")
trafficBad %>%
filter(Day == "")
trafficBad %>%
filter(Hour == "")
trafficBad %>%
filter(Collision_Type == "")
trafficBad %>%
filter(Injury_Type == "")
trafficBad %>%
filter(Primary_Factor == "") #Here are 4 empty values
trafficBad %>%
filter(Location == "")
trafficBad %>%
filter(Latitude == "")
trafficBad %>%
filter(Longitude == "")
#Primary_Factor has 4 empty Values. Lets fill them up
#How much Primary_Factors are there?
trafficBad %>%
group_by(Primary_Factor) %>%
summarise(count = n()) %>%
print(n = Inf)
`summarise()` ungrouping output (override with `.groups` argument)
#Grouping Primary_Factor and Location together and filtering the Locations that are in the empty rows
trafficBad %>%
group_by(Primary_Factor,Location) %>%
summarise(count = n()) %>%
filter(Location == "E MORNINGSIDE & N SMITH" | Location == "ORCHARD & SR37" |
Location == "HINES RD & SR45" | Location == "WALNUT ST")
`summarise()` regrouping output by 'Primary_Factor' (override with `.groups` argument)
#Unfortunatly they are the only Locations with such a Primary_Factor
trafficBad %>%
group_by(Primary_Factor, Injury_Type) %>%
summarise(count = n()) %>%
filter(Injury_Type == "Incapacitating") %>%
arrange(desc(count)) %>%
print(n = Inf) #The most exisiting Primary_Factor with an "Incapacitating" Injura-type is "FAILURE TO YIELD RIGHT OF WAY". I will use this to fill the roows up
`summarise()` regrouping output by 'Primary_Factor' (override with `.groups` argument)
#filling
trafficBad[trafficBad$Primary_Factor == "",] <- trafficBad %>%
filter(Primary_Factor == "") %>%
mutate(Primary_Factor = "FAILURE TO YIELD RIGHT OF WAY")
After a second Data Manipulating step, we can finally foyus o answering questions.
Question on that we can answer with the data are for example: #Which Location is the most dangerous one? #Which Primary_Factor is the most tragic one compared to the Injury_type? #Which Collasion type is the most common? At which Time? On which Month? #What can the city Bloomington do, to reduce there traffic the most dangerous traffic-crashs? #Which time-period is given?
#Which Location is the most dangerous one in case of numbers and injury_type?
trafficBad %>%
group_by(Location) %>%
summarise(number = n()) %>%
filter(number > 3) #"SMITHVILLE & SR37S" hat 8 Unfälle registriert
`summarise()` ungrouping output (override with `.groups` argument)
trafficBad %>%
filter(Location == "SMITHVILLE & SR37S" ) #All of them are Incapacitating
#Visualisierung
most_dangerous0 <- trafficBad %>%
count(Location) %>%
filter(n > 3) %>%
pull(Location)
mostdangerous <- trafficBad %>%
filter(Location %in% most_dangerous0)
ggplot(mostdangerous, aes(Location)) +
geom_bar(aes(fill = Location)) +
theme_dark() +
theme(axis.text.x = element_text(angle = 25, vjust = 1, hjust =1)) +
ylim(0,8) +
theme(legend.position = "none")

#Conclusion: Maybe there should be more Safety measures in ares like "SMITHVILLE & SR446S"; "FULLERTON & SR37S"; HINDS & SR45W; "SR37N & VERNAL
#Which Primary_Factor is the most tragic one compared to the Injury_type?
worst_Primary_Factor <- trafficBad %>%
select(Primary_Factor, Injury_Type) %>%
filter(Injury_Type == "Incapacitating") %>%
group_by(Primary_Factor) %>%
summarise(number_of_Primary_Factor_Cases =n()) %>%
arrange(desc(number_of_Primary_Factor_Cases)) %>%
filter(number_of_Primary_Factor_Cases > 100) #As "incapacitating is the worst injury type, we have to flter the data set
`summarise()` ungrouping output (override with `.groups` argument)
#Visualisierung
worst_Primary_Factor_vis <- trafficBad %>%
select(Primary_Factor, Injury_Type) %>%
filter(Injury_Type == "Incapacitating") %>%
group_by(Primary_Factor) %>%
summarise(number_of_Primary_Factor_Cases =n()) %>%
arrange(desc(number_of_Primary_Factor_Cases)) %>%
filter(number_of_Primary_Factor_Cases > 100) %>%
pull(Primary_Factor)
`summarise()` ungrouping output (override with `.groups` argument)
worst_Primary_Factor_vis <- trafficBad %>%
filter(Primary_Factor %in% worst_Primary_Factor_vis)
ggplot(worst_Primary_Factor_vis, aes(Primary_Factor)) +
geom_bar(fill = "salmon") +
theme_dark()

#Which Collasion type is the most common? At which Time?
trafficBad %>%
group_by(Collision_Type) %>%
count() #2-Car Collision are the most common (with 482 total cases)
#Vis
coll2 <- trafficBad %>%
group_by(Collision_Type) %>%
count() %>%
pull(Collision_Type)
visdata <- trafficBad %>%
filter(Collision_Type %in% coll2)
ggplot(visdata, aes(Collision_Type, fill = Collision_Type)) +
geom_bar() +
theme_dark() +
ggtitle("Most common Collision-Type")

trafficBad %>%
group_by(Hour) %>%
count %>%
filter(n > 20) %>%
arrange(desc(n)) #Most commonly accidents happen on 18 Hour (first place) and 15 + 17 Hour (second Place)
#Vis
ggplot(trafficBad, aes(as.factor(Hour))) +
geom_bar()

#Changing "1700" to "17"
trafficBad[trafficBad$Hour == 1700,"Hour"] <- 17
#Vis again
ggplot(trafficBad, aes(as.factor(Hour))) +
geom_bar(fill = "orange") +
theme_dark() +
labs(x = "Hour") +
ggtitle("Frequency distribution of accidents by time")

#Month
trafficBad %>%
group_by(Month) %>%
count %>%
filter(n > 20) %>%
arrange(desc(n))
#Vis
ggplot(trafficBad, aes(Month, fill = Month)) +
geom_bar() +
theme_dark() +
ggtitle("Most common month of accidents")

#Year
trafficBad %>%
group_by(Year) %>%
count %>%
filter(n > 20) %>%
arrange(desc(n))
#Vis
ggplot(trafficBad, aes(Year, fill = Year)) +
geom_bar() +
theme_dark() +
ggtitle("Most common Year of terrible accidents") #Its like an exponentiell graph. Future looks awefull if it is continueinh like this. Maybe Bloomington got more and more cars/people and has to improve there infrastructure

#Time priod 2003-2015
Now: What can the city Bloomington do, to reduce the most dangerous traffic-crashs? # Most of the accidents happened in October (due to lack of summer tires). Most very bad accidents happen between 3pm and 6pm # In 2015 the accident rate of “very bad car accidents” increased extremely (although, as stated at the beginning, the overall accident frequencies have not decreased). There may have been major problems with the infrastructure. # Most accidents are 2-car types. So there seems to be accidents due to a lack of infrastructure. #Recommendations: Reduce the pace. Expand the trams. Regulate intersections and roundabouts. # ‘Failure to yield right of way’ is the most common cause. It was not granted right before left. # Especially at intersections, additional signs should be added or violations of the rules on the right before left should be punished more # ’SMITHVILE & SR 37S has the most accidents. This place seems particularly dangerous. There may be crossings there that are not easy to spot. # Fortunately, most accidents are no injury and non incapacitating
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KSW4gdGhpcyBwcm9qZWN0IEkgYW5hbHl6ZSB0cmFmZmljIGRhdGEgZnJvbSBCbG9vbWluZ3RvbiBpbiB0aGUgVVNBLiBJIGZvY3VzZWQgb24NCkRhdGEgdmlzdWFsaXNhdGlvbiwgZmVhdHVyZSBlbmdlbmVlcmluZyBhbmQgdHJ5aW5nIHRvIGdpdmUgYWR2aWNlIGZvciB0aGUgY2l0eSBpbg0Kb3JkZXIgdG8gaW1wcm92ZSB0aGUgdHJhZmZpYyBzaXR1YXRpb24uIA0KDQpJIGdvb3QgdGhlIHRyYWZmaWMgZGF0YSBmcm9tIGRhdGEuZ292DQoNCmBgYHtyfQ0KbGlicmFyeShyaW8pDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoY2FyZXQpDQpgYGANCg0KYGBge3J9DQojcmVhZCBkYXRhDQp0cmFmZmljIDwtIGltcG9ydCgiVHJhZmZpY19kYXRhc2V0LmNzdiIpDQp0cmFmZmljIDwtIGFzX3RpYmJsZSh0cmFmZmljKQ0KdHJhZmZpYw0Kb3B0aW9ucyhkcGx5ci53aWR0aCA9IEluZikNCmBgYA0KDQpgYGB7cn0NCiNjaGFuZ2UgY29sdW1uIG5hbWVzDQp0cmFmZmljIDwtIHRyYWZmaWMgJT4lIA0KICBzZWxlY3QoSWQgPSBgTWFzdGVyIFJlY29yZCBOdW1iZXJgLCBZZWFyLCBNb250aCwgRGF5LCBXZWVrZW5kID0gYFdlZWtlbmQ/YCwgSG91ciwgQ29sbGlzaW9uX1R5cGUgPSBgQ29sbGlzaW9uIFR5cGVgLA0KICAgICAgICAgSW5qdXJ5X1R5cGUgPSBgSW5qdXJ5IFR5cGVgLCBQcmltYXJ5X0ZhY3RvciA9IGBQcmltYXJ5IEZhY3RvcmAsIExvY2F0aW9uID0gUmVwb3J0ZWRfTG9jYXRpb24sIExhdGl0dWRlLCBMb25naXR1ZGUpDQpgYGANCg0KRGF0YSBEZXNjcmlwdGlvbjoNCg0KSWQgPSBJZCwgcHJpbWFyeSBLZXkNClllYXIgPSB5ZWFyIG9mIGFjY2lkZW50DQpNb250aCA9IE1vbnRoIG9mIGFjY2lkZW50IA0KZGF5ID0gZGF5IG9mIGFjY2lkZW50IA0Kd2Vla2VuZCA9IHdlZWtlbmQgb3Igbm90IA0KSG91ciA9IEhvdXIgb2YgYWNjaWRlbnQgDQpDb2xsaXNpb25fVHlwZSA9IFR5cGUgb2YgY29sbGlzaW9uIA0KSW5qdXJ5IFR5cGUgID0gVHlwZSBvZiBpbmp1cnkgDQpwcmltYXJ5X0ZhY3RvciA9IFdoYXQgd2FzIHRoZSByZWFzb24gdGhhdCBsZXQgdGhlIGFjY2lkZW50IGhhcHBlbiANCkxvY2F0aW9uID0gV2hlcmUgZGlkIGl0IGhhcHBlbj8gDQpMYXRpdHVkZSANCkxvbmd1dHVkZQ0KDQojSG91ciwgTGF0aXR1ZGUgYW5kIExvZ2l0dWRlIGhhdmUgTkEgQ29sdW1ucw0KYGBge3J9DQojTmEgY2hlY2sNCnNhcHBseSh0cmFmZmljLCBmdW5jdGlvbih4KSBzdW0oaXMubmEoeCkpKQ0KDQpgYGANCg0KI0ZlYXR1cmUgRW5naW5lZXJpbmcNCmBgYHtyfQ0KI1ZhcmlhYmxlIGNoZWNrDQp0cmFmZmljICU+JSANCiAgZ2xpbXBzZSgpDQpgYGANCkkgd2lsbCBjaGFuZ2Ugc29tZSB2YXJpYWJsZXMgdG8gYmV0dGVyIGRhdGEgdHlwZXMNCmBgYHtyfQ0KI2NoYW5naW5nIEhvdXIgdmFyaWFibGUgaW50byBhIGZhY3RvciANCnRyYWZmaWMkSG91ciA8LSBhcy5mYWN0b3IodHJhZmZpYyRIb3VyKQ0KdHJhZmZpYw0KI2NoYW5naW5nIElkIGludG8gZmFjdG9yDQp0cmFmZmljJElkIDwtIGFzLmZhY3Rvcih0cmFmZmljJElkKQ0KI2NoYW5naW5nIHllYXIsbW9udGgsIGRheSBpbnRvIGZhY3Rvcg0KdHJhZmZpYyRNb250aCA8LSBhcy5mYWN0b3IodHJhZmZpYyRNb250aCkNCnRyYWZmaWMkRGF5IDwtIGFzLmZhY3Rvcih0cmFmZmljJERheSkNCnRyYWZmaWMkWWVhciA8LSBhcy5mYWN0b3IodHJhZmZpYyRZZWFyKQ0KDQpgYGANCg0KI1Zpc3VhbGl6YXRpb24NCmBgYHtyfQ0KI0luIHdoaWNoIHllYXIgYXJlIG1vc3Qgb2YgdGhlIGFjY2lkZW50cz8NCmdncGxvdCh0cmFmZmljLCBhZXMoWWVhcikpICsgIyBhbGwgeWVhcnMgYXJlIGVxdWl2YWxlbnQgDQogIGdlb21fYmFyKCkNCiNXZSBjYW4gY2xlYXJseSBzZWUsIHRoYXQgdGhlIGRhdGEgaGFzIGEgdGltZXNwYW4gZnJvbSAyMDAzLTIwMTUuIA0KI0FsdGhvdWdoIHRoZXJlIGFyZSBzb21lIGRpZmZpcmVuY2VzLCB0aGUgYWNjaWRlbnQgcmF0ZSBpcyBvdmVyYWxsIGFyb3VuZCBlcXVhbA0KYGBgDQoNCmBgYHtyfQ0KI0luIHdoaWNoIG1vbnRoPw0KZ2dwbG90KHRyYWZmaWMsIGFlcyhNb250aCwgZmlsbCA9IFllYXIpKSArIA0KI292ZXJhbGwgaW4gbW9udGggMTAgKHBlb3BsZSBoYXZlIHN0aWxsIHN1bW1lciB3aGVlbHMgYW5kIGZvcmdvdCB0byBjaGFuZ2UgdGhlbSkgdGhlIG1vc3QgYW5kIGluIG1vbnRoIDYgdGhlIGxlYXN0DQogIGdlb21fYmFyKCkgKw0KICBmYWNldF9ncmlkKCJZZWFyIikgICNEaWZmZXJlbmNlcyBiZXR3ZWVuIHllYXJzDQpgYGANCg0KYGBge3J9DQojSW4gd2hpY2ggSG91ciBhcmUgdGhlIG1vc3QgYWNjaWRlbnRzPw0KZ2dwbG90KHRyYWZmaWMsIGFlcyhIb3VyKSkgKw0KICBnZW9tX2JhcigpKyANCiAgY29vcmRfY2FydGVzaWFuKGMoMCwyNCkpIzE4OjAwIGFyZSB0aGUgbW9zdCBhY2NpZGVudHMgLS0+IHBlb3BsZSBhcmUgY29taW5nIGZyb20gd29yayB0byBob21lDQojSW4gd2hpY2ggZGF5PyANCmdncGxvdCh0cmFmZmljLCBhZXMoRGF5KSkgKw0KICBnZW9tX2JhcihhZXMoZmlsbCA9IFllYXIpLCBjb2xvciA9ICJibGFjayIpICNPdmVyYWxsIHRoZSBtb3N0IGFjY2lkZW50cyBoYXZlIGJlZW4gb24gU2F0dXJkYXkgKHN1cnByaXNpbmdseSkNCmBgYA0KDQpgYGB7cn0NCiNDaGVjayB0aGUgV2Vla2VuZA0KcSA8LSBpZmVsc2UodHJhZmZpYyREYXkgPT0gMSAmIHRyYWZmaWMkV2Vla2VuZCA9PSAiV2Vla2VuZCIsIFQsIEYpDQp0cmFmZmljWy1xLF0gI1N1cnByaXNpbmdseSAxIGRpZCBub3QgbWVhbiAiTW9uZGF5IiBiZWNhdXNlIHRoZWlyIGFyZSAiV2Vla2RheXMiIGFuZCAiV2Vla2VuZHMiIHdpdGggdGhlIGZhY3RvciAxLiBJIHdvdWxkIGNvbmNsb3VkIHRoYXQgdGhlIERhdGEgaXMgYSBiaXQgbWVzc2kuIFNvIEkgd2lsbCBmaXggaXQuDQoNCiNCZWNhdXNlIHRoZSAiV2Vla2VuZCIgSW5mb3JtYXRpb24gaXMgaW4gIkRheSIgKERheSA2ICYgNyBhcmUgYWx3YXlzIFdlZWtlbmRzKSBJIGNhbiBkZWxldGUgdGhhdCBjb2x1bW4gZnJvbSB0aGUgRGF0YXNldA0KdHJhZmZpYyA8LSB0cmFmZmljICU+JSANCiAgc2VsZWN0KC1XZWVrZW5kKQ0KYGBgDQoNCiNGaXhpbmcgdGhlIE5BwrRzIA0KYGBge3J9DQpzYXBwbHkodHJhZmZpYywgZnVuY3Rpb24oeCkgc3VtKGlzLm5hKHgpKSkNCg0KYGBgDQoNCiNOQS1Ib3VyDQpgYGB7cn0NCnRyYWZmaWMgJT4lIA0KICBmaWx0ZXIoaXMubmEoSG91cikpDQpnZ3Bsb3QodHJhZmZpYywgYWVzKENvbGxpc2lvbl9UeXBlKSkgKyAgI0FuYWx5emluZyB3aXRoIENvbGxpc2lvbiBUeXBlDQogICAgICAgICBnZW9tX2JhcihhZXMoZmlsbCA9IEhvdXIpLCBjb2xvciA9ICJibGFjayIpICNObyBwYXR0ZXJuIGV4aXN0DQoNCmdncGxvdCh0cmFmZmljLCBhZXMoTG9jYXRpb24pKSArICAjQW5hbHl6aW5nIHdpdGggTG9jYXRpb24NCiAgZ2VvbV9iYXIoYWVzKGZpbGwgPSBIb3VyKSwgY29sb3IgPSAiYmxhY2siKSAjVG9vIG1hbnkgDQoNCiNGaWx0ZXJpbmcgYWxsIExvY2F0aW9uIHRoYXQgaGF2ZSBtb3JlIHRoYW4gMTUwIGFjY2lkZW50cyANCnRyYWZmaWMgJT4lIA0KICBncm91cF9ieShMb2NhdGlvbikgJT4lIA0KICBjb3VudChMb2NhdGlvbikgJT4lIA0KICBmaWx0ZXIobiA+PSAxNTApDQojVmlzdWFsaXppbmcNCmEgPC0gdHJhZmZpYyAlPiUgDQogIGZpbHRlcihMb2NhdGlvbiA9PSAiM1JEIFNUInwgTG9jYXRpb24gPT0gIkUgMTBUSCBTVCJ8IExvY2F0aW9uID09ICJFIDNSRCBTVCJ8IExvY2F0aW9uID09ICJTIFdBTE5VVCBTVCJ8IA0KICAgICAgICAgICBMb2NhdGlvbiA9PSAiU1IzN04gJiBWRVJOQUwifCBMb2NhdGlvbiA9PSAiVyAzUkQgU1QiKSAjZmlsdGVyaW5nIHRoZSBtb3N0IGZyZXF1ZW50IHZhcmlhYmxlcw0KZ2dwbG90KGEsIGFlcyhMb2NhdGlvbiwgZmlsbCA9IEhvdXIpKSArDQogIGdlb21fYmFyKGNvbG9yID0gImJsYWNrIikNCiNyZXBsYWNpbmcgSG91cg0KdHJhZmZpYyRIb3VyIDwtIGlmZWxzZSh0cmFmZmljJExvY2F0aW9uID09ICIzUkQgU1QiICYgaXMubmEodHJhZmZpYyRIb3VyKSwgMTUwMCx0cmFmZmljJEhvdXIpDQojVGhlaXIgYXJlIGp1c3QgMjI1IE5BIGluIEhvdXIuIENvbXBhcmVkIHRvIDUzMDAwIHJvd3MsIHRoYXQgaXNudCBhIGxhcmdlIGFtb3VudC4gIFNvIHRoZXJlIGlzIG5vIG5lZWQgdG8gQW5hbHl6ZSBlYWNoIHR5cGUgb2YgYWNjaWRlbnQgaW4gZGV0YWlsLiBUaGVyZWZvcmUgd2Ugd2lsbCB0YWtlIHRoZSBtb3N0IGNvbW1vbiBhY2NpZGVudC1UaW1lLCB3aGljaCBpcyAxODowMC4gDQp0cmFmZmljICU+JSANCiAgZ3JvdXBfYnkoSG91cikgJT4lIA0KICBjb3VudCgpICU+JSANCiAgZmlsdGVyKG4gPiAzMDAwKQ0KdHJhZmZpYyA8LSB0cmFmZmljICU+JSANCiAgcmVwbGFjZV9uYShsaXN0KEhvdXIgPSAxNzAwKSkNCmBgYA0KQWZ0ZXIgd2UgZml4ZWQgdGhlICJIb3VyIiBjb2x1bW4sIHdlIHdpbGwgZm9jdXNlIG9uIHRoZSBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlDQojTGF0aXR1ZGUgDQpgYGB7cn0NCiNXaGljaCBMb2NhdGlvbnMgaGF2ZSBOQS1MYXRpdHVkZXM/DQpMb2NhdGlvbk5BIDwtIHRyYWZmaWMgJT4lIA0KICBmaWx0ZXIoaXMubmEoTGF0aXR1ZGUpKSAlPiUgDQogIGdyb3VwX2J5KExvY2F0aW9uKSAlPiUgDQogIHN1bW1hcmlzZSgpICU+JSANCiAgcHJpbnQobiA9IDEwMCkNCiNGdXJ0aGVybW9yZSwgYWxsIExvY2F0aW9ucyB3aXRoIGFuIE5BIGFyZSBvbmx5IGF2YWlsYWJsZSBvbmNlIA0KdHJhZmZpYyAlPiUgDQogIGZpbHRlcihpcy5uYShMYXRpdHVkZSkpICU+JSANCiAgZ3JvdXBfYnkoTG9jYXRpb24pICU+JSANCiAgY291bnQoTG9jYXRpb24pICU+JSANCiAgYXJyYW5nZShkZXNjKExvY2F0aW9uKSkgDQoNCiNMYXRpdHVkZSBmb3IgZWFjaCBMb2NhdGlvbg0KdHJhZmZpYyAlPiUgDQogIGZpbHRlcihMb2NhdGlvbiA9PSAiV0FMTlVUICYgV0lOU0xPVyIpICU+JSANCiAgc2VsZWN0KExhdGl0dWRlKQ0KI0JlY2F1c2Ugb2YgdGhlIHJlcGl0aXRpb24gaXRzIGlzIGJldHRlciB0byB3cml0ZSBhIGZ1bmN0aW9uIGhlcmU6IA0KTGF0aUZ1bmMgPC0gZnVuY3Rpb24oeCkgew0KICB0cmFmZmljICU+JSANCiAgICBmaWx0ZXIoTG9jYXRpb24gPT0geCkgJT4lIA0KICAgIHNlbGVjdChMYXRpdHVkZSkNCn0NCiN0ZXN0aW5nIGZ1bmN0aW9uDQpMYXRpRnVuYygiV0FMTlVUICYgV0lOU0xPVyIpICN3b3JrcyBwZXJmZWN0DQojZmlsbGluZyBXYWxudXQgJiBXaW5zbG93DQp0cmFmZmljW2lzLm5hKHRyYWZmaWMkTGF0aXR1ZGUpICYgdHJhZmZpYyRMb2NhdGlvbiA9PSAiV0FMTlVUICYgV0lOU0xPVyIsICJMYXRpdHVkZSJdIDwtIDM5LjENCg0KIzE3VEggJiBMSVNNT1JFDQpMYXRpRnVuYygiMTdUSCAmIExJU01PUkUiKSAjaGF0IG51ciBlaW4gTkEgLS0+IGF1ZmhlYmVuIGbDvHIgc3DDpHRlciAoTUFSS0lFUlQgQUxTICJBUkdIIikNCiMyTkQgJiBDT0xMRUdFIE1BTEwNCkxhdGlGdW5jKCIyTkQgJiBDT0xMRUdFIE1BTEwiKSAjcmVwbGFjaW5nIE5BIGFuZCBmaXhpbmcgd3JvbmcgMCB2YWx1ZQ0KdHJhZmZpY1tpcy5uYSh0cmFmZmljJExhdGl0dWRlKSAmIHRyYWZmaWMkTG9jYXRpb24gPT0gIjJORCAmIENPTExFR0UgTUFMTCIsICJMYXRpdHVkZSJdIDwtIDM5LjINCnRyYWZmaWNbdHJhZmZpYyRMYXRpdHVkZSA9PSAwICYgdHJhZmZpYyRMb2NhdGlvbiA9PSAiMk5EICYgQ09MTEVHRSBNQUxMIiwgIkxhdGl0dWRlIl0gPC0gMzkuMg0KIzNSRCAmIEJBTExBTlRJTkUNCkxhdGlGdW5jKCIzUkQgJiBCQUxMQU5USU5FIikNCnRyYWZmaWNbaXMubmEodHJhZmZpYyRMYXRpdHVkZSkgJiB0cmFmZmljJExvY2F0aW9uID09ICIzUkQgJiBCQUxMQU5USU5FIiwgIkxhdGl0dWRlIl0gPC0gMzkuMg0KIzNSRCAmIEhBV1RIT1JORQ0KTGF0aUZ1bmMoIjNSRCAmIEhBV1RIT1JORSIpDQp0cmFmZmljW2lzLm5hKHRyYWZmaWMkTGF0aXR1ZGUpICYgdHJhZmZpYyRMb2NhdGlvbiA9PSAiM1JEICYgSEFXVEhPUk5FIiwgIkxhdGl0dWRlIl0gPC0gMzkuMg0KIzNSRCAmIExJQkVSVFkNCkxhdGlGdW5jKCIzUkQgJiBMSUJFUlRZIikNCnRyYWZmaWNbaXMubmEodHJhZmZpYyRMYXRpdHVkZSkgJiB0cmFmZmljJExvY2F0aW9uID09ICIzUkQgJiBMSUJFUlRZIiwgIkxhdGl0dWRlIl0gPC0gMzkuMg0KdHJhZmZpYyRMYXRpdHVkZQ0KDQojSSBjb3VsZCBnbyBvbiBhbmQgZmlsbCBvdXQgdGhlIHJlc3Qgb2YgdGhlIE5BJ3MgbGlrZSB0aGlzLiBIb3dldmVyLCBiZWNhdXNlIHRoZXJlIGFyZSBoYXJkbHkgYW55IGRldmlhdGlvbnMgaW4gbGF0aXR1ZGUgdGhlIGxvY2F0aW9uIGNhbiBjb250YWlucyBzbWFsbGVyIGRldmlhdGlvbnMgYW55d2F5IGR1ZSB0byBpdHMgbGVuZ3RoIG9yIG1lYXN1cmVtZW50IGluYWNjdXJhY2llcywgdGhlIGZpbGxpbmcgd2l0aCB0aGUgbWVhbiB2YWx1ZSB3aWxsIG5vdCBoYXZlIGEgbmVnYXRpdmUgZWZmZWN0IG9uIHRoZSBkYXRhIHNldC4gVGhlIDAgdmFsdWVzIGFyZSBtdWNoIG1vcmUgaW1wb3J0YW50Lg0KdHJhZmZpYyAlPiUNCiAgZmlsdGVyKCFpcy5uYShMYXRpdHVkZSkpICU+JSANCiAgc3VtbWFyaXNlKG1lYW4oTGF0aXR1ZGUpKSAjSGVyZSB3ZSBoYXZlIHRvIGZpbHRlciB0aGUgMC12YWx1ZXMgb3V0LCB0byBnZXQgYW4gYWNjdXJhdGUgbWVhbi4NCg0KI0JlY2F1c2Ugb2YgQmxvb21pbmd0b24gTG9jYXRpb24gYXMgYSBjaXR5IGluIHRoZSBVU0EgaXQgaGFzIHRvIGhhdmUgYSBMb25naXR1ZGUNCiNvZiAzOC8zOS4NCiNUaGVyZSBhcmUgc29tZSB2YWx1ZXMgd2hpY2ggaGF2ZSBhIExvbmdpdHVkZSB1bmRlciAzOC4gVGhhdHMgYSBwcm9ibGVtIGJlY2F1c2UNCiNpdHMgbm90IGluIHRoZSByYW5nZSBvZiBibG9vbWluZ3Rvbi4gTWF5YmUgdGhlcmUgaXMgYSBtaXN0YWtlIGluIHRoZSBkYXRlIG9yIA0KI3RoZXkgdGhlIGRhdGFzZXQgaW5jbHVkZXMgZGF0YSBmcm9tIHRoZSBzdGF0ZSBpbmRpYW5hIGluIGdlbmVyYWwuIEJlY2F1c2UgaXRzIA0KI2RpZmZpY3VsdCB0byBmaW5kIHRoYXQgb3V0IChiZWNhdXNlIGkgYW0gbGl2aW5nIGluIGdlcm1hbnkgOkQpIGkgd2lsbCBjb3JyZWN0IA0KI3RoZSBkYXRhc2V0IGFzIGZvbGxvd3M6DQp0cmFmZmljICU+JSANCiAgZmlsdGVyKExhdGl0dWRlIDw9IDM4ICYgTGF0aXR1ZGUgPT0gMC4wMDAwMCkgDQp0cmFmZmljICU+JSANCiAgZmlsdGVyKExhdGl0dWRlID49IDM4ICYgTGF0aXR1ZGUgIT0gMC4wMDAwMCkgJT4lIA0KICBzdW1tYXJpc2UobWVhbihMYXRpdHVkZSkpICNUaGUgbWVhbiBpcyAzOS4yLCBzbyBsZXRzIGZpbGwgdGhpcyB2YWx1ZSBpbnRvIHRoZSBOQSdzDQoNCiNGaWxsaW5nIE5BJ3Mgd2l0aCBtZWFuDQp0cmFmZmljIDwtIHRyYWZmaWMgJT4lIA0KICByZXBsYWNlX25hKGxpc3QoTGF0aXR1ZGUgPSAzOS4yKSkNCiNBbGwgVmFrdWVzIHdoaWNoIGFyZSB1bmRyIDM4IHdpbGwgYmUgc2V0IGFzIHRoZSBtZWFuIHRvby4NCnRyYWZmaWNbdHJhZmZpYyRMYXRpdHVkZSA8PSAzOCwgIkxhdGl0dWRlIl0gPC0gMzkuMg0KI2NoZWNrDQp0cmFmZmljICU+JSANCiAgZmlsdGVyKExhdGl0dWRlIDw9IDM4KSAjbmljZQ0KYGBgDQoNCiNMb25naXR1ZGUgKEJsb29taW5ndG9ucyBMb25naXR1ZGUgaXMgLTg4IChzZWFyY2hlZCBpbiBnb29nbGUpDQpgYGB7cn0NCiNOQcK0cyBpbiBsb25naXR1ZGUgDQp0cmFmZmljICU+JSANCiAgZmlsdGVyKGlzLm5hKExvbmdpdHVkZSkpICU+JSANCiAgc2VsZWN0KExvY2F0aW9uKSAlPiUgDQogIHByaW50KG4gPSAxMDApDQoNCiNCTE9PTUZJRUxEICYgTElCRVJUWQ0KdHJhZmZpYyAlPiUgDQogIGZpbHRlcihMb2NhdGlvbiA9PSAiQkxPT01GSUVMRCAmIExJQkVSVFkiKSAlPiUgDQogIHNlbGVjdChMb25naXR1ZGUsIExhdGl0dWRlKSAjVGhlIExvbmdpdHVkZSBpcyAwLiBUaGF0IHdvdWxkIG1lYW4sIHRoYXQgdGhpcyBwbGFjZSBpbiBCbG9vbWluZ3RvbiBpcyBpbiBHcmVhdCBCcml0YWluLiBJdHMgb2J2aW91cywgdGhhdCBpdCBjYW50IGJlIHJpZ2h0LCBzbyBpIHdpbGwgY2hhbmdlIHRoZSBMb25naXR1ZGUgdG8gdGhlIHJlYWwgb25lIGZvdW5kIGluIHRoZSBpbnRlcm5ldC4NCnRyYWZmaWNbdHJhZmZpYyRMb2NhdGlvbiA9PSAiQkxPT01GSUVMRCAmIExJQkVSVFkiLCAiTG9uZ2l0dWRlIl0gPC0gLTg4DQoNCiNidWlsZGluZyBmdW5jdGlvbg0KTG9uZ2kgPC0gZnVuY3Rpb24oeCkgew0KICB0cmFmZmljICU+JSANCiAgICBmaWx0ZXIoTG9jYXRpb24gPT0geCkgJT4lIA0KICAgIHNlbGVjdChMb25naXR1ZGUpDQp9DQpMb25naSgiQkxPT01GSUVMRCAmIExJQkVSVFkiKSAjd29ya3MgbmljZWx5DQoNCiNET0REUyAmIFJPR0VSUyANCkxvbmdpKCJET0REUyAmIFJPR0VSUyIpDQp0cmFmZmljW3RyYWZmaWMkTG9jYXRpb24gPT0gIkRPRERTICYgUk9HRVJTIiwgIkxvbmdpdHVkZSJdIDwtIC04Ni41DQoNCiNIQVJNT05ZDQpMb25naSgiSEFSTU9OWSIpDQp0cmFmZmljW3RyYWZmaWMkTG9jYXRpb24gPT0gIkhBUk1PTlkiLCAiTG9uZ2l0dWRlIl0gPC0gLTg4DQoNCiNBTExFTiAmIFBBVFRFUlNPTg0KTG9uZ2koIkFMTEVOICYgUEFUVEVSU09OIikNCnRyYWZmaWNbdHJhZmZpYyRMb2NhdGlvbiA9PSAiQUxMRU4gJiBQQVRURVJTT04iLCAiTG9uZ2l0dWRlIl0gPC0gLTg2LjUNCg0KIzJORCAmIExJTkNPTE4NCkxvbmdpKCIyTkQgJiBMSU5DT0xOIikNCnRyYWZmaWNbdHJhZmZpYyRMb2NhdGlvbiA9PSAiMk5EICYgTElOQ09MTiIsICJMb25naXR1ZGUiXSA8LSAtODYuNQ0KDQojRk9SUkVTVCBQQVJLICYgU1I0NlcNCkxvbmdpKCJGT1JSRVNUIFBBUksgJiBTUjQ2VyIpDQp0cmFmZmljW3RyYWZmaWMkTG9jYXRpb24gPT0gIkZPUlJFU1QgUEFSSyAmIFNSNDZXIiwgIkxvbmdpdHVkZSJdIDwtIC04Ni42DQoNCiNSSE9SRVIgJiBTQVJFDQpMb25naSgiUkhPUkVSICYgU0FSRSIpDQp0cmFmZmljW3RyYWZmaWMkTG9jYXRpb24gPT0gIlJIT1JFUiAmIFNBUkUiLCAiTG9uZ2l0dWRlIl0gPC0gLTg2LjUNCg0KI0NMVUJIT1VTRSAmIEtJTlNFUg0KTG9uZ2koIkNMVUJIT1VTRSAmIEtJTlNFUiIpDQp0cmFmZmljW3RyYWZmaWMkTG9jYXRpb24gPT0gIkNMVUJIT1VTRSAmIEtJTlNFUiIsICJMb25naXR1ZGUiXSA8LSAtODgNCg0KI1NNSVRIDQpMb25naSgiU01JVEgiKQ0KdHJhZmZpY1t0cmFmZmljJExvY2F0aW9uID09ICJTTUlUSCIsICJMb25naXR1ZGUiXSA8LSAtODgNCg0KI1dBTE5VVCAmIFdJTlNMT1cNCkxvbmdpKCJXQUxOVVQgJiBXSU5TTE9XIikNCnRyYWZmaWNbdHJhZmZpYyRMb2NhdGlvbiA9PSAiV0FMTlVUICYgV0lOU0xPVyIsICJMb25naXR1ZGUiXSA8LSAtODYuNQ0KDQojQkxPT01GSUVMRCAmIFBBVFRFUlNPTg0KTG9uZ2koIkJMT09NRklFTEQgJiBQQVRURVJTT04iKQ0KdHJhZmZpY1t0cmFmZmljJExvY2F0aW9uID09ICJCTE9PTUZJRUxEICYgUEFUVEVSU09OIiwgIkxvbmdpdHVkZSJdIDwtIC04OA0KDQojMk5EICYgQ09MTEVHRSBNQUxMDQpMb25naSgiMk5EICYgQ09MTEVHRSBNQUxMIikNCnRyYWZmaWNbdHJhZmZpYyRMb2NhdGlvbiA9PSAiMk5EICYgQ09MTEVHRSBNQUxMIiwgIkxvbmdpdHVkZSJdIDwtIC04Ni41DQoNCiMxN1RIICYgTElTTU9SRQ0KTG9uZ2koIjE3VEggJiBMSVNNT1JFIikNCnRyYWZmaWNbdHJhZmZpYyRMb2NhdGlvbiA9PSAiMTdUSCAmIExJU01PUkUiLCAiTG9uZ2l0dWRlIl0gPC0gLTg4DQoNCiNDT1JZICYgVEhJUkQNCkxvbmdpKCJDT1JZICYgVEhJUkQiKQ0KdHJhZmZpY1t0cmFmZmljJExvY2F0aW9uID09ICJDT1JZICYgVEhJUkQiLCAiTG9uZ2l0dWRlIl0gPC0gLTg2LjYNCg0KIzNSRCAmIEJBTExBTlRJTkUNCkxvbmdpKCIzUkQgJiBCQUxMQU5USU5FIikNCnRyYWZmaWNbdHJhZmZpYyRMb2NhdGlvbiA9PSAiM1JEICYgQkFMTEFOVElORSIsICJMb25naXR1ZGUiXSA8LSAtODYuNQ0KDQojM1JEICYgSEFXVEhPUk5FDQpMb25naSgiM1JEICYgSEFXVEhPUk5FIikNCnRyYWZmaWNbdHJhZmZpYyRMb2NhdGlvbiA9PSAiM1JEICYgSEFXVEhPUk4iLCAiTG9uZ2l0dWRlIl0gPC0gLTg2LjUNCg0KI1BFVEUgRUxMSVMNCkxvbmdpKCJQRVRFIEVMTElTIikNCnRyYWZmaWNbdHJhZmZpYyRMb2NhdGlvbiA9PSAiUEVURSBFTExJUyIsICJMb25naXR1ZGUiXSA8LSAtODYuNQ0KDQojM1JEICYgSEFXVEhPUk5FDQpMb25naSgiM1JEICYgSEFXVEhPUk5FIikNCnRyYWZmaWNbdHJhZmZpYyRMb2NhdGlvbiA9PSAiM1JEICYgSEFXVEhPUk5FIiwgIkxvbmdpdHVkZSJdIDwtIC04Ni41DQoNCiNWRVJNSUxZQSAmIFdBTE5VVA0KTG9uZ2koIjNSRCAmIExJQkVSVFkiKQ0KdHJhZmZpY1t0cmFmZmljJExvY2F0aW9uID09ICIzUkQgJiBMSUJFUlRZIiwgIkxvbmdpdHVkZSJdIDwtIC04Ni42DQpMb25naSgiM1JEICYgTElCRVJUWSIpDQp0cmFmZmljW3RyYWZmaWMkTG9jYXRpb24gPT0gIjNSRCAmIExJQkVSVFkiLCAiTG9uZ2l0dWRlIl0gPC0gLTg2LjYNCkxvbmdpKCJBTExFTiAmIFRJTU9USFkiKQ0KdHJhZmZpY1t0cmFmZmljJExvY2F0aW9uID09ICJBTExFTiAmIFRJTU9USFkiLCAiTG9uZ2l0dWRlIl0gPC0gLTg2LjYNCg0KI0FsbCBvdGhlcnMgaGF2ZSBMb25naXR1ZGUgODYuNQ0KTG9uZ2koIkZBSVJGQVggJiBNQ0NPUk1JQ0siKQ0KTG9uZ2koIkNBTkFEQSAmIFNBUkUiKQ0KTG9uZ2koIkxFT05BUkQgU1BSSU5HUyAmIFNSNDVXIikNCkxvbmdpKCJWRVJNSUxZQSAmIFdBTE5VVCIpDQpMb25naSgiQkxVRSBTS1kgJiBGT1JSRVNUIFBBUksiKQ0KTG9uZ2koIlNPVVRIRVJOICYgV0FMTlVUIikNCkxvbmdpKCIzUkQgJiBTV0FJTiIpDQpMb25naSgiRE9ERFMgJiBNQURJU09OIikNCkxvbmdpKCJPTEQgU1RBVEUgUk9BRCAzNyBTT1VUSCAmIFdFU1QgQ0hVTUxFWSIpDQp0cmFmZmljIDwtIHRyYWZmaWMgJT4lIA0KICByZXBsYWNlX25hKGxpc3QoTG9uZ2l0dWRlID0gODYuNSkpDQoNCiNmaW5hbCBOQSBjaGVjaw0Kc2FwcGx5KHRyYWZmaWMsIGZ1bmN0aW9uKHgpIHN1bShpcy5uYSh4KSkpDQoNCiNOQSBGaWxsaW5nIGRvbmUgOkQNCiN0aGVyZSBhcmUgc29tZSAiMCIgdmFsdWVzLCB3aGljaCBoYXZlIHRvIGJlIGZpeGVkDQp0cmFmZmljW3RyYWZmaWMkTG9uZ2l0dWRlID09IDAsICJMb25naXR1ZGUiXSA8LSAtODYuNQ0KDQpgYGANCk5vdyB3ZSBmaW5pc2hlZCB0aGUgZGF0YSBjbGVhbmluZy9lbmdlbmVlcmluZyBwYXJ0IGFuZCBkaWQgc29tZSBkYXRhIGV4cGxvcmF0aW9uLiANClN1cnVseSB3ZSBnaXZlIGFkdmljZSB0byBmaXggdHJhZmZpYyBpbiBnZW5lcmFsLiBCdXQgd2UgY2FuIGZva3VzIG9uIHRoZSB3b3JzdA0KY2FzZXMgYW5kIHNlZSB3aGF0IHdlIGNhbiBkbyB0aGVyZS4NCiNXaGljaCBMb2NhdGlvbiBoYXMgdGhlIG1vc3QgZGFuZ2Vyb3VzIHJvdXRlLyB0aGUgYmFkZXN0IEluanVyeV9UeXBlDQpgYGB7cn0NCiNXaGljaCBpbmp1cnkgdHlwIGV4c2lzdD8NCmdncGxvdCh0cmFmZmljLCBhZXMoeCA9IEluanVyeV9UeXBlKSkgKw0KICBnZW9tX2JhcigpDQoNCiMiSW5jYXBhY2l0YXRpZyIgYW5kICJmYXRhbCIgYXJlIGludGVyZXN0aW5nIGZvciB1cywgYmVjYXVzZSB3ZSB3YW50IHRvIG1ha2UgZHJpdmluZyBjYXIgaW4gQmxvb21pbmd0b24gc2FmZXIuIFRoZXJlZm9yZSB3ZSBuZWVkIHRvIGtub3cgdGhlIG1vc3QgdW5zYWZlIGxvY2F0aW9ucw0KdHJhZmZpY0JhZCA8LSB0cmFmZmljICU+JSANCiAgZmlsdGVyKEluanVyeV9UeXBlID09ICJJbmNhcGFjaXRhdGluZyIgfCBJbmp1cnlfVHlwZSA9PSAgIkZhdGFsIikNCg0KdHJhZmZpY0JhZCAlPiUgDQogIGdyb3VwX2J5KExvY2F0aW9uKSAlPiUgDQogIHN1bW1hcmlzZSgpICU+JSANCiAgcHJpbnQobiA9IEluZikNCiNhcyB3ZSBjYW4gc2VlLCB3ZSBoYXZlIG9uZSBMb2NhdGlvbiB0aGF0IGlzIGVtcHR5ICIiLiBXZSBoYXZlIHRvIGZpeCB0aGF0Lg0KDQpgYGANCg0KI0ZpbGxpbmcgYW4gZW1wdHkgIiIgdmFsdWUNCmBgYHtyfQ0KdHJhZmZpY0JhZCAlPiUgDQogIGZpbHRlcihMb2NhdGlvbiA9PSAiIikgDQp0cmFmZmljQmFkICU+JSANCiAgZ3JvdXBfYnkoTG9jYXRpb24pICU+JSANCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUgDQogIHN1bW1hcmlzZSh0b3RhbF9udW1iZXJfb2ZfTG9jYXRpb25zID0gc3VtKGNvdW50KSkNCg0KI3NpbmNlIHdlIGhhdmUgMTIwNCBkaWZmZXJlbnQgTG9jYXRpb24gd2UgY291bGQgdHJ5IHRvIGJ1aWxkIGEgbXVsdGkgbGFiZWwgY2xhc3NpZmllci4gSG93ZXZlciwgdGhlcmUgaXMganVzdCBvbmUgbWlzc2lnIHZhbHVlIGluIG9uZSByb3cuIFRoZXJlZm9yIGl0cyBzaW1wbHkgYmV0dGVyIHRvIGFuYWx5emUgdGhlIG1vc3QgY29tbW9uIExvY2F0aW9ucyB3aXRoIHRoZSBMYXRpZHVlIGFuZCBMb25naXR1ZGUuDQp0cmFmZmljQmFkICU+JSANCiAgZ3JvdXBfYnkoTG9jYXRpb24pICU+JSANCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhjb3VudCkpICAgICAgICAjVGhlIG1vc3QgY29tbW9uIExvY2F0aW9uIGhhcyBvbmx5IGEgZnJlcXVlbmN5IG9mIDggDQpgYGANCg0KQmVjYXVzZSBvZiB0aGUgbG93IGZyZXF1ZW5jeSB3ZSB3aWxsIGRvIGEgY2hpLXNxdWFyZSB0ZXN0IHRvIGNoZWNrLCBpZiB0aGVyZSBhcmUgY29ycmVsYXRpb25zIGJldHdlZW4gdGhlIExvY2F0aW9uIGFuZCB0aGUgQ29sbGlzaW9ucy1UeXBlDQpIeXBvdGhlc2lzOiANCiNIMTogVGhlcmUgaXMgYSBjb3JyZWxhdGlvbiBiZXR3ZWVuIExvY2F0aW9uIGFuZCBDb2xsaXNpb25zLVR5cGUNCiNIMDogVGhlcmUgaXMgbm8gY29ycmVsYXRpb24gYmV0d2VlbiBMb2NhdGlvbiBhbmQgQ29sbGlzaW9ucy1UeXBlDQpgYGB7cn0NCmtyZXV6dGFiZWxsZTIgPC0gdGFibGUodHJhZmZpY0JhZCRMb2NhdGlvbiwgdHJhZmZpY0JhZCRDb2xsaXNpb25fVHlwZSkNCmMyIDwtIGNoaXNxLnRlc3Qoa3JldXp0YWJlbGxlMiwgc2ltdWxhdGUucC52YWx1ZSA9IFQpDQpjMiAjcC12YWx1ZSA8IDUlOyBUaGVyZWZvcmUgYSBjb3JyZWxhdGlvbiBleGlzdHMuIA0KDQojV2UgaGFlIHRvIGNoZWNrIGZvciAiMS1DYXIiIGJlY2F1c2Ugb2YgdGhlIGVtcHR5IHZhbHVlLg0KdHJhZmZpY0JhZCAlPiUgDQogIGZpbHRlcihDb2xsaXNpb25fVHlwZSA9PSAiMS1DYXIiKSAlPiUgDQogIGdyb3VwX2J5KExvY2F0aW9uKSAlPiUgDQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lIA0KICBhcnJhbmdlKGRlc2MoY291bnQpKSAlPiUgDQogIHByaW50KG4gPSBJbmYpICM0ICIxLUNhciIgQ29sbGlzaW9uc3R5cGUgaW4gIkhJTkRTICYgU1I0NVciDQoNCiNhZGRpbmcgIkhJTkRTICYgU1I0NVciIGZvciB0aGF0IHR5cGUNCnRyYWZmaWNCYWRbdHJhZmZpY0JhZCRJZCA9PSAxODA3ODc3LCBdIDwtIHRyYWZmaWNCYWQgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihJZCA9PSAxODA3ODc3KSAlPiUgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKExvY2F0aW9uID0gIkhJTkRTICYgU1I0NVciKQ0KYGBgDQoNCg0KYGBge3J9DQojQ2hlY2tpbmcgYWxsIGNvbHVtbnMgdG8gc2VlIGlmIHRoZXJlIGlzIGFueSBlbXB0eSB2YWx1ZQ0Kc2FwcGx5KHRyYWZmaWNCYWQsIGZ1bmN0aW9uKHgpIHN1bShpcy5uYSh4KSkpICNObyBOYQ0KI01hYmUgZW1wdHkgb25lIGxpa2UgIiINCnRyYWZmaWNCYWQgJT4lIA0KICBmaWx0ZXIoTW9udGggPT0gIiIpDQp0cmFmZmljQmFkICU+JSANCiAgZmlsdGVyKERheSA9PSAiIikNCnRyYWZmaWNCYWQgJT4lIA0KICBmaWx0ZXIoSG91ciA9PSAiIikNCnRyYWZmaWNCYWQgJT4lIA0KICBmaWx0ZXIoQ29sbGlzaW9uX1R5cGUgPT0gIiIpDQp0cmFmZmljQmFkICU+JSANCiAgZmlsdGVyKEluanVyeV9UeXBlID09ICIiKQ0KdHJhZmZpY0JhZCAlPiUgDQogIGZpbHRlcihQcmltYXJ5X0ZhY3RvciA9PSAiIikgI0hlcmUgYXJlIDQgZW1wdHkgdmFsdWVzDQp0cmFmZmljQmFkICU+JSANCiAgZmlsdGVyKExvY2F0aW9uID09ICIiKQ0KdHJhZmZpY0JhZCAlPiUgDQogIGZpbHRlcihMYXRpdHVkZSA9PSAiIikNCnRyYWZmaWNCYWQgJT4lIA0KICBmaWx0ZXIoTG9uZ2l0dWRlID09ICIiKQ0KDQojUHJpbWFyeV9GYWN0b3IgaGFzIDQgZW1wdHkgVmFsdWVzLiBMZXRzIGZpbGwgdGhlbSB1cA0KI0hvdyBtdWNoIFByaW1hcnlfRmFjdG9ycyBhcmUgdGhlcmU/DQp0cmFmZmljQmFkICU+JSANCiAgZ3JvdXBfYnkoUHJpbWFyeV9GYWN0b3IpICU+JSANCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUgDQogIHByaW50KG4gPSBJbmYpDQoNCiNHcm91cGluZyBQcmltYXJ5X0ZhY3RvciBhbmQgTG9jYXRpb24gdG9nZXRoZXIgYW5kIGZpbHRlcmluZyB0aGUgTG9jYXRpb25zIHRoYXQgYXJlIGluIHRoZSBlbXB0eSByb3dzDQp0cmFmZmljQmFkICU+JSANCiAgZ3JvdXBfYnkoUHJpbWFyeV9GYWN0b3IsTG9jYXRpb24pICU+JSANCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUgDQogIGZpbHRlcihMb2NhdGlvbiA9PSAiRSBNT1JOSU5HU0lERSAmIE4gU01JVEgiIHwgTG9jYXRpb24gPT0gIk9SQ0hBUkQgJiBTUjM3IiB8IA0KICAgICAgICAgICBMb2NhdGlvbiA9PSAiSElORVMgUkQgJiBTUjQ1IiB8IExvY2F0aW9uID09ICJXQUxOVVQgU1QiKQ0KI1VuZm9ydHVuYXRseSB0aGV5IGFyZSB0aGUgIG9ubHkgTG9jYXRpb25zIHdpdGggc3VjaCBhIFByaW1hcnlfRmFjdG9yDQp0cmFmZmljQmFkICU+JSANCiAgZ3JvdXBfYnkoUHJpbWFyeV9GYWN0b3IsIEluanVyeV9UeXBlKSAlPiUgDQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lIA0KICBmaWx0ZXIoSW5qdXJ5X1R5cGUgPT0gIkluY2FwYWNpdGF0aW5nIikgJT4lIA0KICBhcnJhbmdlKGRlc2MoY291bnQpKSAlPiUgDQogIHByaW50KG4gPSBJbmYpICNUaGUgbW9zdCBleGlzaXRpbmcgUHJpbWFyeV9GYWN0b3Igd2l0aCBhbiAiSW5jYXBhY2l0YXRpbmciIEluanVyYS10eXBlIGlzICJGQUlMVVJFIFRPIFlJRUxEIFJJR0hUIE9GIFdBWSIuIEkgd2lsbCB1c2UgdGhpcyB0byBmaWxsIHRoZSByb293cyB1cA0KDQojZmlsbGluZw0KdHJhZmZpY0JhZFt0cmFmZmljQmFkJFByaW1hcnlfRmFjdG9yID09ICIiLF0gPC0gdHJhZmZpY0JhZCAlPiUgDQogIGZpbHRlcihQcmltYXJ5X0ZhY3RvciA9PSAiIikgJT4lIA0KICBtdXRhdGUoUHJpbWFyeV9GYWN0b3IgPSAiRkFJTFVSRSBUTyBZSUVMRCBSSUdIVCBPRiBXQVkiKQ0KYGBgDQpBZnRlciBhIHNlY29uZCBEYXRhIE1hbmlwdWxhdGluZyBzdGVwLCB3ZSBjYW4gZmluYWxseSBmb3l1cyBvIGFuc3dlcmluZyBxdWVzdGlvbnMuDQoNClF1ZXN0aW9uIG9uIHRoYXQgd2UgY2FuIGFuc3dlciB3aXRoIHRoZSBkYXRhIGFyZSBmb3IgZXhhbXBsZToNCiNXaGljaCBMb2NhdGlvbiBpcyB0aGUgbW9zdCBkYW5nZXJvdXMgb25lPw0KI1doaWNoIFByaW1hcnlfRmFjdG9yIGlzIHRoZSBtb3N0IHRyYWdpYyBvbmUgY29tcGFyZWQgdG8gdGhlIEluanVyeV90eXBlPyANCiNXaGljaCBDb2xsYXNpb24gdHlwZSBpcyB0aGUgbW9zdCBjb21tb24/IEF0IHdoaWNoIFRpbWU/IE9uIHdoaWNoIE1vbnRoPw0KI1doYXQgY2FuIHRoZSBjaXR5IEJsb29taW5ndG9uIGRvLCB0byByZWR1Y2UgdGhlcmUgdHJhZmZpYyB0aGUgbW9zdCBkYW5nZXJvdXMgdHJhZmZpYy1jcmFzaHM/IA0KI1doaWNoIHRpbWUtcGVyaW9kIGlzIGdpdmVuPw0KDQpgYGB7cn0NCiNXaGljaCBMb2NhdGlvbiBpcyB0aGUgbW9zdCBkYW5nZXJvdXMgb25lIGluIGNhc2Ugb2YgbnVtYmVycyBhbmQgaW5qdXJ5X3R5cGU/DQp0cmFmZmljQmFkICU+JSANCiAgZ3JvdXBfYnkoTG9jYXRpb24pICAlPiUgDQogIHN1bW1hcmlzZShudW1iZXIgPSBuKCkpICU+JSANCiAgZmlsdGVyKG51bWJlciA+IDMpICMiU01JVEhWSUxMRSAmIFNSMzdTIiBoYXQgOCBVbmbDpGxsZSByZWdpc3RyaWVydCANCg0KdHJhZmZpY0JhZCAlPiUgDQogIGZpbHRlcihMb2NhdGlvbiA9PSAiU01JVEhWSUxMRSAmIFNSMzdTIiApICNBbGwgb2YgdGhlbSBhcmUgSW5jYXBhY2l0YXRpbmcgDQojVmlzdWFsaXNpZXJ1bmcgDQptb3N0X2Rhbmdlcm91czAgPC0gdHJhZmZpY0JhZCAlPiUgDQogIGNvdW50KExvY2F0aW9uKSAlPiUgDQogIGZpbHRlcihuID4gMykgJT4lIA0KICBwdWxsKExvY2F0aW9uKQ0KDQptb3N0ZGFuZ2Vyb3VzIDwtIHRyYWZmaWNCYWQgJT4lIA0KICBmaWx0ZXIoTG9jYXRpb24gJWluJSBtb3N0X2Rhbmdlcm91czApDQoNCmdncGxvdChtb3N0ZGFuZ2Vyb3VzLCBhZXMoTG9jYXRpb24pKSArDQogIGdlb21fYmFyKGFlcyhmaWxsID0gTG9jYXRpb24pKSArDQogIHRoZW1lX2RhcmsoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMjUsIHZqdXN0ID0gMSwgaGp1c3QgPTEpKSArDQogIHlsaW0oMCw4KSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCiNDb25jbHVzaW9uOiBNYXliZSB0aGVyZSBzaG91bGQgYmUgbW9yZSBTYWZldHkgbWVhc3VyZXMgaW4gYXJlcyBsaWtlICJTTUlUSFZJTExFICYgU1I0NDZTIjsgIkZVTExFUlRPTiAmIFNSMzdTIjsgSElORFMgJiBTUjQ1VzsgIlNSMzdOICYgVkVSTkFMDQoNCmBgYA0KDQojV2hpY2ggUHJpbWFyeV9GYWN0b3IgaXMgdGhlIG1vc3QgdHJhZ2ljIG9uZSBjb21wYXJlZCB0byB0aGUgSW5qdXJ5X3R5cGU/IA0KYGBge3J9DQp3b3JzdF9QcmltYXJ5X0ZhY3RvciA8LSB0cmFmZmljQmFkICU+JSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3QoUHJpbWFyeV9GYWN0b3IsIEluanVyeV9UeXBlKSAlPiUgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKEluanVyeV9UeXBlID09ICJJbmNhcGFjaXRhdGluZyIpICU+JSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cF9ieShQcmltYXJ5X0ZhY3RvcikgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZShudW1iZXJfb2ZfUHJpbWFyeV9GYWN0b3JfQ2FzZXMgPW4oKSkgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFycmFuZ2UoZGVzYyhudW1iZXJfb2ZfUHJpbWFyeV9GYWN0b3JfQ2FzZXMpKSAlPiUgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKG51bWJlcl9vZl9QcmltYXJ5X0ZhY3Rvcl9DYXNlcyA+IDEwMCkgI0FzICJpbmNhcGFjaXRhdGluZyBpcyB0aGUgd29yc3QgaW5qdXJ5IHR5cGUsIHdlIGhhdmUgdG8gZmx0ZXIgdGhlIGRhdGEgc2V0IA0KI1Zpc3VhbGlzaWVydW5nDQp3b3JzdF9QcmltYXJ5X0ZhY3Rvcl92aXMgPC0gdHJhZmZpY0JhZCAlPiUgDQogIHNlbGVjdChQcmltYXJ5X0ZhY3RvciwgSW5qdXJ5X1R5cGUpICU+JSANCiAgZmlsdGVyKEluanVyeV9UeXBlID09ICJJbmNhcGFjaXRhdGluZyIpICU+JSANCiAgZ3JvdXBfYnkoUHJpbWFyeV9GYWN0b3IpICU+JSANCiAgc3VtbWFyaXNlKG51bWJlcl9vZl9QcmltYXJ5X0ZhY3Rvcl9DYXNlcyA9bigpKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhudW1iZXJfb2ZfUHJpbWFyeV9GYWN0b3JfQ2FzZXMpKSAlPiUgDQogIGZpbHRlcihudW1iZXJfb2ZfUHJpbWFyeV9GYWN0b3JfQ2FzZXMgPiAxMDApICU+JSANCiAgcHVsbChQcmltYXJ5X0ZhY3RvcikNCndvcnN0X1ByaW1hcnlfRmFjdG9yX3ZpcyA8LSB0cmFmZmljQmFkICU+JSANCiAgZmlsdGVyKFByaW1hcnlfRmFjdG9yICVpbiUgd29yc3RfUHJpbWFyeV9GYWN0b3JfdmlzKQ0KDQpnZ3Bsb3Qod29yc3RfUHJpbWFyeV9GYWN0b3JfdmlzLCBhZXMoUHJpbWFyeV9GYWN0b3IpKSArDQogIGdlb21fYmFyKGZpbGwgPSAic2FsbW9uIikgKw0KICB0aGVtZV9kYXJrKCkNCmBgYA0KDQojV2hpY2ggQ29sbGFzaW9uIHR5cGUgaXMgdGhlIG1vc3QgY29tbW9uPyBBdCB3aGljaCBUaW1lPyANCmBgYHtyfQ0KdHJhZmZpY0JhZCAlPiUgDQogIGdyb3VwX2J5KENvbGxpc2lvbl9UeXBlKSAlPiUgDQogIGNvdW50KCkgICMyLUNhciBDb2xsaXNpb24gYXJlIHRoZSBtb3N0IGNvbW1vbiAod2l0aCA0ODIgdG90YWwgY2FzZXMpDQojVmlzIA0KY29sbDIgPC0gdHJhZmZpY0JhZCAlPiUgDQogIGdyb3VwX2J5KENvbGxpc2lvbl9UeXBlKSAlPiUgDQogIGNvdW50KCkgJT4lICANCiAgcHVsbChDb2xsaXNpb25fVHlwZSkNCg0KdmlzZGF0YSA8LSB0cmFmZmljQmFkICU+JSANCiAgZmlsdGVyKENvbGxpc2lvbl9UeXBlICVpbiUgY29sbDIpDQpnZ3Bsb3QodmlzZGF0YSwgYWVzKENvbGxpc2lvbl9UeXBlLCBmaWxsID0gQ29sbGlzaW9uX1R5cGUpKSArDQogIGdlb21fYmFyKCkgKw0KICB0aGVtZV9kYXJrKCkgKw0KICBnZ3RpdGxlKCJNb3N0IGNvbW1vbiBDb2xsaXNpb24tVHlwZSIpDQoNCnRyYWZmaWNCYWQgJT4lIA0KICBncm91cF9ieShIb3VyKSAlPiUgDQogIGNvdW50ICU+JSANCiAgZmlsdGVyKG4gPiAyMCkgJT4lIA0KICBhcnJhbmdlKGRlc2MobikpICNNb3N0IGNvbW1vbmx5IGFjY2lkZW50cyBoYXBwZW4gb24gMTggSG91ciAoZmlyc3QgcGxhY2UpIGFuZCAxNSArIDE3IEhvdXIgKHNlY29uZCBQbGFjZSkNCiNWaXMNCmdncGxvdCh0cmFmZmljQmFkLCBhZXMoYXMuZmFjdG9yKEhvdXIpKSkgKw0KICBnZW9tX2JhcigpIA0KI0NoYW5naW5nICIxNzAwIiB0byAiMTciDQp0cmFmZmljQmFkW3RyYWZmaWNCYWQkSG91ciA9PSAxNzAwLCJIb3VyIl0gPC0gMTcNCiNWaXMgYWdhaW4NCmdncGxvdCh0cmFmZmljQmFkLCBhZXMoYXMuZmFjdG9yKEhvdXIpKSkgKw0KICBnZW9tX2JhcihmaWxsID0gIm9yYW5nZSIpICsNCiAgdGhlbWVfZGFyaygpICsNCiAgbGFicyh4ID0gIkhvdXIiKSArDQogIGdndGl0bGUoIkZyZXF1ZW5jeSBkaXN0cmlidXRpb24gb2YgYWNjaWRlbnRzIGJ5IHRpbWUiKQ0KDQojTW9udGgNCnRyYWZmaWNCYWQgJT4lIA0KICBncm91cF9ieShNb250aCkgJT4lIA0KICBjb3VudCAlPiUgDQogIGZpbHRlcihuID4gMjApICU+JSANCiAgYXJyYW5nZShkZXNjKG4pKQ0KI1Zpcw0KZ2dwbG90KHRyYWZmaWNCYWQsIGFlcyhNb250aCwgZmlsbCA9IE1vbnRoKSkgKw0KICBnZW9tX2JhcigpICsNCiAgdGhlbWVfZGFyaygpICsNCiAgZ2d0aXRsZSgiTW9zdCBjb21tb24gbW9udGggb2YgYWNjaWRlbnRzIikNCiNZZWFyDQp0cmFmZmljQmFkICU+JSANCiAgZ3JvdXBfYnkoWWVhcikgJT4lIA0KICBjb3VudCAlPiUgDQogIGZpbHRlcihuID4gMjApICU+JSANCiAgYXJyYW5nZShkZXNjKG4pKQ0KI1Zpcw0KZ2dwbG90KHRyYWZmaWNCYWQsIGFlcyhZZWFyLCBmaWxsID0gWWVhcikpICsNCiAgZ2VvbV9iYXIoKSArDQogIHRoZW1lX2RhcmsoKSArDQogIGdndGl0bGUoIk1vc3QgY29tbW9uIFllYXIgb2YgdGVycmlibGUgYWNjaWRlbnRzIikgI0l0cyBsaWtlIGFuIGV4cG9uZW50aWVsbCBncmFwaC4gRnV0dXJlIGxvb2tzIGF3ZWZ1bGwgaWYgaXQgaXMgY29udGludWVpbmggbGlrZSB0aGlzLiBNYXliZSBCbG9vbWluZ3RvbiBnb3QgbW9yZSBhbmQgbW9yZSBjYXJzL3Blb3BsZSBhbmQgaGFzIHRvIGltcHJvdmUgdGhlcmUgaW5mcmFzdHJ1Y3R1cmUNCiNUaW1lIHByaW9kIDIwMDMtMjAxNQ0KYGBgDQoNCk5vdzogV2hhdCBjYW4gdGhlIGNpdHkgQmxvb21pbmd0b24gZG8sIHRvIHJlZHVjZSB0aGUgbW9zdCBkYW5nZXJvdXMgdHJhZmZpYy1jcmFzaHM/IA0KIyBNb3N0IG9mIHRoZSBhY2NpZGVudHMgaGFwcGVuZWQgaW4gT2N0b2JlciAoZHVlIHRvIGxhY2sgb2Ygc3VtbWVyIHRpcmVzKS4gTW9zdCB2ZXJ5IGJhZCBhY2NpZGVudHMgaGFwcGVuIGJldHdlZW4gM3BtIGFuZCA2cG0NCiMgSW4gMjAxNSB0aGUgYWNjaWRlbnQgcmF0ZSBvZiAidmVyeSBiYWQgY2FyIGFjY2lkZW50cyIgaW5jcmVhc2VkIGV4dHJlbWVseSAoYWx0aG91Z2gsIGFzIHN0YXRlZCBhdCB0aGUgYmVnaW5uaW5nLCB0aGUgb3ZlcmFsbCBhY2NpZGVudCBmcmVxdWVuY2llcyBoYXZlIG5vdCBkZWNyZWFzZWQpLiBUaGVyZSBtYXkgaGF2ZSBiZWVuIG1ham9yIHByb2JsZW1zIHdpdGggdGhlIGluZnJhc3RydWN0dXJlLg0KIyBNb3N0IGFjY2lkZW50cyBhcmUgMi1jYXIgdHlwZXMuIFNvIHRoZXJlIHNlZW1zIHRvIGJlIGFjY2lkZW50cyBkdWUgdG8gYSBsYWNrIG9mIGluZnJhc3RydWN0dXJlLg0KI1JlY29tbWVuZGF0aW9uczogUmVkdWNlIHRoZSBwYWNlLiBFeHBhbmQgdGhlIHRyYW1zLiBSZWd1bGF0ZSBpbnRlcnNlY3Rpb25zIGFuZCByb3VuZGFib3V0cy4NCiMgJ0ZhaWx1cmUgdG8geWllbGQgcmlnaHQgb2Ygd2F5JyBpcyB0aGUgbW9zdCBjb21tb24gY2F1c2UuIEl0IHdhcyBub3QgZ3JhbnRlZCByaWdodCBiZWZvcmUgbGVmdC4NCiMgRXNwZWNpYWxseSBhdCBpbnRlcnNlY3Rpb25zLCBhZGRpdGlvbmFsIHNpZ25zIHNob3VsZCBiZSBhZGRlZCBvciB2aW9sYXRpb25zIG9mIHRoZSBydWxlcyBvbiB0aGUgcmlnaHQgYmVmb3JlIGxlZnQgc2hvdWxkIGJlIHB1bmlzaGVkIG1vcmUNCiMgJ1NNSVRIVklMRSAmIFNSIDM3UyBoYXMgdGhlIG1vc3QgYWNjaWRlbnRzLiBUaGlzIHBsYWNlIHNlZW1zIHBhcnRpY3VsYXJseSBkYW5nZXJvdXMuIFRoZXJlIG1heSBiZSBjcm9zc2luZ3MgdGhlcmUgdGhhdCBhcmUgbm90IGVhc3kgdG8gc3BvdC4NCiMgRm9ydHVuYXRlbHksIG1vc3QgYWNjaWRlbnRzIGFyZSBubyBpbmp1cnkgYW5kIG5vbiBpbmNhcGFjaXRhdGluZw==